package org.softmed.rest.editor.comps.utils.list;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.Border;

import net.miginfocom.swing.MigLayout;

import org.restlet.data.Response;
import org.restlet.resource.StringRepresentation;
import org.softmed.rest.editor.EditorUtil;
import org.softmed.rest.editor.commons.SwingUtil;
import org.softmed.rest.editor.commons.URIProvider;
import org.softmed.rest.editor.comps.SimpleEditor;
import org.softmed.rest.editor.comps.browser.SelectionListener;
import org.softmed.rest.editor.comps.full.getDeletePanel;
import org.softmed.swing.IconManager;

public class ListAddingPanel extends JPanel implements ActionListener,
		KeyListener, SelectionListener {

	JTextField id = new JTextField();
	JButton createNew = new JButton(IconManager.add);
	JButton find = new JButton(IconManager.search);
	JButton browse = new JButton(IconManager.searchInList);

	JButton detailToggle = new JButton(IconManager.zoomIn);

	String uriFieldName;
	SimpleEditor parentEditor;
	private Class editorClass;
	private JDialog dialog;
	private SimpleEditor editor;
	private PagedListPanel plist;
	private ListFieldPanel listPanel;
	private String label;
	private JPanel panel;

	public ListAddingPanel(String label, String uriFieldName,
			Class editorClass, SimpleEditor parent, PagedListPanel plist,
			ListFieldPanel listPanel) throws Throwable {
		// setBackground(Color.WHITE);

		createNew.setToolTipText("Create new object and add to list");
		find
				.setToolTipText("Add the object with the id refered in the text field");
		browse.setToolTipText("Browse for an object to add to the list");
		id.setToolTipText("Write the id of the object to add to the list");

		setButtonBorder(BorderFactory.createLineBorder(Color.GRAY));

		// id.setBorder(BorderFactory.createEtchedBorder());

		this.label = label;
		this.listPanel = listPanel;
		this.plist = plist;

		this.editorClass = editorClass;
		this.parentEditor = parent;
		this.uriFieldName = uriFieldName;

		if (!SimpleEditor.class.isAssignableFrom(editorClass))
			throw new RuntimeException(
					"Editor class for field must be a SimpleEditor");

		panel = new JPanel();
		MigLayout layout = new MigLayout("left, insets "
				+ EditorUtil.smallestInsets + ", gap 0");
		panel.setLayout(layout);
		// panel.add(new JLabel("Add to list"), "w 60!");
		panel.add(new JLabel("ID"), "w 16!");
		panel.add(id, "w 40!, h 20!");
		panel.add(find);
		panel.add(browse);
		panel.add(createNew);
		// panel.add(Box.createHorizontalStrut(15));
		// panel.add(minMax);
		add(panel);

		panel.setBackground(Color.WHITE);
		setBackground(Color.WHITE);

		BoxLayout box = new BoxLayout(this, BoxLayout.PAGE_AXIS);
		setLayout(box);

		detailToggle.addActionListener(this);
		detailToggle.setToolTipText("Show more data for all objects in list");

		EditorUtil.configButton(detailToggle);
		detailToggle.setActionCommand("maximize");

		EditorUtil.configButton(createNew);
		EditorUtil.configButton(find);
		EditorUtil.configButton(browse);

		createNew.addActionListener(this);
		find.addActionListener(this);
		browse.addActionListener(this);

		id.addKeyListener(this);

		disable();

	}

	protected void configButton(JButton button) {
		button.setBorder(EditorUtil.buttonBorder);
		SwingUtil.setSize(button, EditorUtil.buttonHeightAndWidth,
				EditorUtil.buttonHeightAndWidth);
	}

	private void setButtonBorder(Border border) {
		createNew.setBorder(border);
		find.setBorder(border);
		browse.setBorder(border);

		detailToggle.setBorder(border);

	}

	public void setFullBackground(Color orange) {
		panel.setBackground(orange);
		setBackground(orange);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		try {
			Object source = e.getSource();

			if (e.getSource() == detailToggle) {
				if (detailToggle.getActionCommand().equals("maximize")) {
					detailToggle.setActionCommand("minimize");
					detailToggle.setIcon(IconManager.zoomOut);
					detailToggle
							.setToolTipText("Hide data for all objects in list");
					maximize();
				} else {
					detailToggle.setActionCommand("maximize");
					detailToggle.setIcon(IconManager.zoomIn);
					detailToggle
							.setToolTipText("Show more data for all objects in list");
					minimize();
				}

				return;
			}

			if (source == createNew) {
				EditorUtil.showUpdatePanel();

				getChildEditor();

				editor.createNew();

				addObjectToList();

				EditorUtil.hideUpdatePanel();

				return;
			}

			if (source == find) {

				findAndSetChildObjectToField();

				return;
			}

			if (source == browse) {
				dialog = new JDialog();
				dialog.setTitle("Select one of the " + label.toLowerCase()
						+ ":");
				dialog.setModal(true);

				org.softmed.rest.editor.comps.browser.PagedListPanel pagedListPanel = new org.softmed.rest.editor.comps.browser.PagedListPanel(
						parentEditor.getUriProvider());

				getChildEditor();

				String entURI = editor.getClassURI();
				pagedListPanel.setBaseClassURI(entURI + "?detailed&size=30");
				pagedListPanel.setSelectionListener(this);

				dialog.add(pagedListPanel);
				dialog.pack();
				dialog.setResizable(false);
				dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);

				dialog.setVisible(true);
			}
		} catch (Throwable t) {
			EditorUtil.hideUpdatePanel();
			t.printStackTrace();
			JOptionPane.showMessageDialog(this, t.getMessage(), "Error",
					JOptionPane.ERROR_MESSAGE);
		}

	}

	private void minimize() {
		List<SimpleEditor> editors = plist.getItemList().getEditors();
		for (SimpleEditor simpleEditor : editors) {
			simpleEditor.minimize();
		}

	}

	private void maximize() {
		List<SimpleEditor> editors = plist.getItemList().getEditors();
		for (SimpleEditor simpleEditor : editors) {
			simpleEditor.maximize();
		}

	}

	protected void findAndSetChildObjectToField() throws NoSuchMethodException,
			InstantiationException, IllegalAccessException,
			InvocationTargetException, Throwable, IOException {
		String text = id.getText();
		Integer findID = null;
		try {
			findID = Integer.valueOf(text);
		} catch (Throwable t) {
			EditorUtil.hideUpdatePanel();
			t.printStackTrace();
			JOptionPane.showMessageDialog(this, "Invalid ID", "Error",
					JOptionPane.ERROR_MESSAGE);
			return;
		}

		EditorUtil.showUpdatePanel();

		getChildEditor();

		String entURI = editor.getClassURI() + "/" + findID;

		editor.loadEntity(entURI + "?detailed");

		addObjectToList();

		EditorUtil.hideUpdatePanel();
	}

	protected void getChildEditor() throws NoSuchMethodException,
			InstantiationException, IllegalAccessException,
			InvocationTargetException {
		Constructor constructor = editorClass.getConstructor(URIProvider.class);
		editor = (SimpleEditor) constructor.newInstance(parentEditor
				.getUriProvider());
	}

	@Override
	public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_ENTER) {
			try {
				findAndSetChildObjectToField();
			} catch (Throwable t) {
				EditorUtil.hideUpdatePanel();
				t.printStackTrace();
				JOptionPane.showMessageDialog(this, t.getMessage(), "Error",
						JOptionPane.ERROR_MESSAGE);
			}
		}

	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void selected(Object object) {

		try {

			getChildEditor();

			editor.setEntity(object);

			addObjectToList();

			dialog.setVisible(false);
			dialog = null;

		} catch (Throwable t) {
			EditorUtil.hideUpdatePanel();
			t.printStackTrace();
			JOptionPane.showMessageDialog(this, t.getMessage(), "Error",
					JOptionPane.ERROR_MESSAGE);
		}

	}

	protected void addObjectToList() throws Throwable {
		// add it to the parent field - post
		String fieldURI = parentEditor.getEntityURI() + "/" + uriFieldName;
		String childURI = editor.getEntityURI();
		EditorUtil.showUpdatePanel();
		Response response = parentEditor.getClient().post(fieldURI,
				new StringRepresentation(childURI));
		EditorUtil.hideUpdatePanel();
		if (response.getStatus().getCode() != 201) {
			EditorUtil.hideUpdatePanel();
			throw new RuntimeException("Error adding field " + uriFieldName
					+ ". " + response.getEntity().getText());
		}

		// refresh the list, go to last page
		refreshListShowLastPage();
	}

	private void refreshListShowLastPage() throws Throwable {

		long itemsPerPage = plist.pagedList.getItemsPerPage();
		// if (itemsPerPage == 0)
		// itemsPerPage = 20;

		int existingChilds = plist.itemList.editors.size();

		if (existingChilds < itemsPerPage) {
			plist.itemList.addSimpleNonEnabledEditor(editor.getEntity());
		}
		// refresh the nav buttons;
		plist.increaseListContent();
		revalidate();
	}

	public void enabled() {
		id.setEnabled(true);
		createNew.setEnabled(true);
		find.setEnabled(true);
		browse.setEnabled(true);
	}

	public void disabled() {
		id.setEnabled(false);
		createNew.setEnabled(false);
		find.setEnabled(false);
		browse.setEnabled(false);
	}

	public JButton getDetailToggle() {
		return detailToggle;
	}

}
